package com.zyl.blog.common.builder;

import com.zyl.blog.common.config.TreeConfig;
import com.zyl.blog.common.service.ITreeNode;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog
 * @Package: com.zyl.common.builder
 * @ClassName: UniversalTreeBuilder
 * @Description: 企业级通用树构建器
 * @Author FinalFantasy
 * @Date 2025/2/19-10:11
 */
public class UniversalTreeBuilder {

    /**
     * 通用树构建方法（支持泛型、循环引用检测、并行处理）
     * @param nodes 原始节点列表
     * @param config 树配置
     * @return 完整的树结构
     */
    public static <T extends Serializable> List<ITreeNode<T>> buildTree(
            List<? extends ITreeNode<T>> nodes,
            TreeConfig<T, T> config
    ) {

        // 1. 预检查
        validateNodes(nodes);

        // 2. 并行流处理开关
        Stream<? extends ITreeNode<T>> stream = config.isParallel() ?
                nodes.parallelStream() : nodes.stream();

        // 3. 构建快速索引
        Map<T, ITreeNode<T>> nodeMap = stream.collect(
                Collectors.toMap(ITreeNode::getId, Function.identity()));

        // 4. 构建父子关系
        List<ITreeNode<T>> roots = new ArrayList<>();
        nodes.forEach(node -> {
            T parentId = node.getParentId();
            if (config.getRootPredicate().test(node)) {
                roots.add(node);
            } else if (nodeMap.containsKey(parentId)) {
                ITreeNode<T> parent = nodeMap.get(parentId);
                parent.getChildren().add(node);
            }
        });

        // 5. 排序处理
        if (config.getComparator() != null) {
            sortNodes(roots, config.getComparator());
        }

        // 6. 循环引用检测
        if (config.isCheckCyclic()) {
            roots.forEach(root -> checkCyclic(root, new HashSet<>()));
        }

        return roots;
    }

    private static <T extends Serializable> void validateNodes(List<? extends ITreeNode<T>> nodes) {
        // ID唯一性校验
        Set<T> ids = nodes.stream()
                .map(ITreeNode::getId)
                .collect(Collectors.toSet());
        if (ids.size() != nodes.size()) {
            throw new IllegalArgumentException("节点ID必须唯一");
        }
    }

    private static <T extends Serializable> void sortNodes(List<ITreeNode<T>> nodes,
                                                           Comparator<ITreeNode<T>> comparator) {
        nodes.sort(comparator);
        nodes.forEach(node -> {
            if (!node.getChildren().isEmpty()) {
                sortNodes(node.getChildren(), comparator);
            }
        });
    }

    private static <T extends Serializable> void checkCyclic(ITreeNode<T> node, Set<T> path) {
        T nodeId = node.getId();
        if (path.contains(nodeId)) {
            throw new IllegalStateException("发现循环引用: " + path);
        }
        path.add(nodeId);
        node.getChildren().forEach(child ->
                checkCyclic(child, new HashSet<>(path))
        );
    }

}